home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 4 / Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso / Pearls / midi / misc / Midi2TeX / src / tp_midi.c < prev    next >
C/C++ Source or Header  |  1994-03-24  |  25KB  |  855 lines

  1. /* Output from p2c, the Pascal-to-C translator */
  2. /* From input file "tp_midi.pas" */
  3.  
  4. #define TP_MIDI_G
  5. #include "tp_midi.h"
  6. #include <stdlib.h>
  7. #include <math.h>
  8. #include <string.h>
  9.  
  10.  
  11. /********************************************/
  12. Char *StaffIndex(Result,No)
  13. Char *Result;
  14. int No;
  15. {
  16.   /********************************************/
  17.   switch (No) {
  18.  
  19.   case 1:
  20.     strcpy(Result, "i");
  21.     break;
  22.  
  23.   case 2:
  24.     strcpy(Result, "ii");
  25.     break;
  26.  
  27.   case 3:
  28.     strcpy(Result, "iii");
  29.     break;
  30.  
  31.   case 4:
  32.     strcpy(Result, "iv");
  33.     break;
  34.  
  35.   case 5:
  36.     strcpy(Result, "v");
  37.     break;
  38.  
  39.   case 6:
  40.     strcpy(Result, "vi");
  41.     break;
  42.  
  43.   case 7:
  44.     strcpy(Result, "vii");
  45.     break;
  46.  
  47.   case 8:
  48.     strcpy(Result, "viii");
  49.     break;
  50.  
  51.   case 9:
  52.     strcpy(Result, "ix");
  53.     break;
  54.  
  55.   case 10:
  56.     strcpy(Result, "x");
  57.     break;
  58.  
  59.   default:
  60.     ErrorExit(8L);
  61.     break;
  62.   }/* case */
  63.   return Result;
  64. }
  65.  
  66.  
  67. /**********************************************/
  68. Char *GetPortees(Result)
  69. Char *Result;
  70. {
  71.   /**********************************************/
  72.   Char TmpSTr[256];
  73.   int curtr;
  74.   uchar curinstr, staff, StartStaff, nStaffsInInstr;
  75.   boolean StartFound;
  76.   TrackRecord *WITH;
  77.   Char STR1[256];
  78.   Char STR2[256];
  79.  
  80.   *TmpSTr = '\0';
  81.   StartFound = false;
  82.   for (curinstr = 1; curinstr <= 1; curinstr++)
  83.   {   /* this version only supports one instrument */
  84.     staff = 1;
  85.     
  86.     for (curtr = (int) (ntracks - 1); curtr >= 0; curtr--) { /* With */
  87.       WITH = &TrackArray[TrackOrder[curtr] - 1];  
  88.       if (!WITH->Skip) {
  89.     if (!StartFound) {
  90.       if (WITH->Instrument) {
  91.         StartStaff = staff;
  92.         StartFound = true;
  93.         nStaffsInInstr = 1;  
  94.       }
  95.     } else {
  96.       if (WITH->Instrument)
  97.         nStaffsInInstr++;   
  98.     }
  99.     staff++;
  100.       } /* if Skip */
  101.     }  /* for next curtr */
  102.     sprintf(TmpSTr, "\\nbportees%s=%s",
  103.         StaffIndex(STR1, StartStaff), B2S(STR2, nStaffsInInstr));
  104.   }  /* for next curinstr */
  105.   strcpy(Result, TmpSTr);
  106.   return Result;
  107. }
  108.  
  109.  
  110. /**********************************************/
  111. Void WriteTexHeader()
  112. {
  113.   /**********************************************/
  114.   unsigned short Year;
  115.   unsigned short Month;
  116.   unsigned short Day;
  117.   unsigned short DoW;
  118.   Char STR1[256], STR2[256];
  119.   Char STR4[256];
  120.  
  121.   /*  getdate(&d);  */
  122.   fprintf(TexFile,
  123.     "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
  124.   fprintf(TexFile, "%%    MIDI2TeX %s translation \n",VERSION);
  125.   fprintf(TexFile, "%%           of MIDI file : \n");
  126.   fprintf(TexFile, "%%          %s%s\n", MidiFileName.n, MidiFileName.e);
  127.   fprintf(TexFile, "%% \n");
  128.   fprintf(TexFile, "%%   Written by Hans Kuykens, Ad Verbruggen\n");
  129.   fprintf(TexFile,
  130.     "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
  131.   fprintf(TexFile, "\\input musicnft\n");
  132.   fprintf(TexFile, "\\input musictex\n");
  133.   fprintf(TexFile, "\\input musicadd\n");
  134.   fprintf(TexFile, "\\input musictrp\n");
  135.   fprintf(TexFile, "\\normal\n");
  136.   if (SizingChanged) {
  137.     fprintf(TexFile, "\\hsize %ldmm ",ScoreWidth / 10);
  138.     fprintf(TexFile, "\\vsize %ldmm\n",ScoreHeight / 10);
  139.     fprintf(TexFile, "\\musicsize=%ld\n", MusicSize);
  140.     fprintf(TexFile, "\\elemskip=%ldpt%%\n",(long)(ElemSkip / PT ));
  141.     }
  142.   if (ninstruments > 0) {
  143.     fprintf(TexFile, "\\def\\nbinstruments{%ld}\n",
  144.           ntracks - NoOfSkips - nTracksInInstr + 1);
  145.     fprintf(TexFile, "%s\n", GetPortees(STR4));
  146.   } else
  147.     fprintf(TexFile, "\\def\\nbinstruments{%d}\n",
  148.         (int)(ntracks - NoOfSkips));
  149.  
  150.   fprintf(TexFile,"\\generalsignature{%d}\\relax\n",PieceContr.KeySign);
  151.   fprintf(TexFile,"\\def\\thename{%s}\n",TeXFileName.n);
  152.   fprintf(TexFile,"%% \\centerline{\\enorme PUT A NAME HERE and remove }\n");
  153.   fprintf(TexFile, "\\medskip\\centerline{\\moyen \\thename}\n");
  154.   fprintf(TexFile, "\\rightline{translation by MIDI2TeX}\n");
  155.   fprintf(TexFile, "\\rightline{by H.J.P. Kuykens}\n");
  156.   fprintf(TexFile, "\\def\\date{\\number\\day -\\number\\month -\\number\\year}\n");
  157.   fprintf(TexFile, "\\headline={\\ifnum\\pageno>1 \\otherpage \\else\\frontpage\\fi}\n");
  158.   fprintf(TexFile, "\\def\\frontpage{\\hfil \\tenrm\\date}\n");
  159.   fprintf(TexFile, "\\def\\otherpage{\\tenrm \\thename \\hfil \\tenrm\\date}\n");
  160.   fflush(TexFile);
  161. }
  162.  
  163.  
  164. /*-----------------------------------------------*/
  165. long FindStaff(ThisTrack)
  166. long ThisTrack;
  167. {
  168.   /*-----------------------------------------------*/
  169.   /* Watch it ! If the track is in an instrument than the parameter string */
  170.   /* must be altered of cleftoks#                                          */
  171.   long i, j;
  172.  
  173.   i = ntracks;
  174.   j = 1;
  175.   while (TrackOrder[i - 1] != ThisTrack) {
  176.     if (!TrackArray[TrackOrder[i - 1] - 1].Skip)
  177.       j++;
  178.     i--;
  179.   }
  180.   return j;
  181. }  /* FindStaff */
  182.  
  183. /*-----------------------------------------------*/
  184. Char *FindClefStaff(Result, ThisTrack)
  185. Char *Result;
  186. long ThisTrack;
  187. {
  188.   /*-----------------------------------------------*/
  189.   long i, j, k;
  190.   Char STR1[256],C[2];
  191.  
  192.  
  193.   i = ntracks;
  194.   j = 1;
  195.   k = 1;
  196.   sprintf(C,"%d",TrackArray[ThisTrack-1].Clef);
  197.   while (TrackOrder[i - 1] != ThisTrack) {
  198.     if (!TrackArray[TrackOrder[i - 1] - 1].Skip) {
  199.       if (TrackArray[TrackOrder[i - 1] - 1].Instrument)
  200.     k++;
  201.       else
  202.     j++;
  203.     }
  204.     i--;
  205.   }
  206.   switch (k) {
  207.  
  208.   case 1:
  209.     sprintf(Result, "\\cleftoks%s{{%s}{0}{0}{0}}", StaffIndex(STR1, (int)j),C);
  210.     break;
  211.  
  212.   case 2:
  213.     sprintf(Result, "\\cleftoks%s{{0}{%s}{0}{0}}", StaffIndex(STR1, (int)j),C);
  214.     break;
  215.  
  216.   case 3:
  217.     sprintf(Result, "\\cleftoks%s{{0}{0}{%s}{0}}", StaffIndex(STR1, (int)j),C);
  218.     break;
  219.  
  220.   case 4:
  221.     sprintf(Result, "\\cleftoks%s{{0}{0}{0}{%s}}", StaffIndex(STR1, (int)j),C);
  222.     break;
  223.  
  224.   default:
  225.     Warning("Something wrong with cleftoks#, check it out !");
  226.     strcpy(Result, "\\cleftoks??");
  227.     break;
  228.   }
  229.  
  230.   return Result;
  231. }  /* FindClefStaff */
  232.  
  233.  
  234. /********************************************/
  235. static Void FinishTeXHeader(num, den)
  236. unsigned int num, den;
  237. {
  238.   /********************************************/
  239.   int i;
  240.   Char STR2[256];
  241.   int FORLIM;
  242.  
  243.   fprintf(TexFile, "\\generalmeter{\\meterfrac{%d}{%d}}%%\n",num, Power(2, den));
  244.   FORLIM = ntracks;
  245.   /* determine clefs */
  246.   for (i = 1; i <= FORLIM; i++) {
  247.     if (TrackArray[i - 1].Clef == BASS)
  248.       fprintf(TexFile, "%s\n", FindClefStaff(STR2, (long)i));
  249.   }
  250.   fprintf(TexFile,
  251.       "%%\\raggedlinestrue %% uncomment for ragged right lines \n");
  252.   fprintf(TexFile, "%%\\relativeaccidentals\n");
  253.   fprintf(TexFile, "\\debutmorceau\n");
  254.   /*
  255.   if (NoteSkip == 20)
  256.     fprintf(TexFile, "\\autolines{16}{5}{16} \n");
  257.   else
  258.     fprintf(TexFile, "\\autolines{16}{7}{16} \n");
  259.   */
  260.   TeXHeaderFinished = true;
  261.   fflush(TexFile);
  262. }
  263.  
  264.  
  265. /********************************************/
  266. Void ChangeContext(N)
  267. NoteRecord *N;
  268. {
  269.   /********************************************/
  270.   Char STR1[256];
  271.  
  272.   switch (N->Event) {
  273.  
  274.   case KEYSIGN:
  275.     fprintf(TexFile, "\\signaturegenerale{%s}\\changecontext%%\n",
  276.         B2S(STR1, (char) N->NoteVal));   /* N->NoteVal is uchar */
  277.     PieceContr.KeySign = N->NoteVal;
  278.     PieceContr.Minor = N->Velocity;
  279.     break;
  280.  
  281.   case SIGNATURE:
  282.     fprintf(TexFile, "\\generalmeter{\\meterfrac{%d}{%d}}%%\n",
  283.         N->NoteVal, Power(2, N->Velocity));
  284.     fprintf(TexFile, "\\changecontext%%\n");
  285.     PieceContr.Num = N->NoteVal;
  286.     PieceContr.Den = N->Velocity;
  287.     PieceContr.TicksPerMeasure = 4 * PieceContr.Division * PieceContr.Num  /
  288.                  Power(2, PieceContr.Den);
  289.     if (!PieceContr.PartOverRule)
  290.       PieceContr.PartTime = PieceContr.TicksPerMeasure / PieceContr.Num;
  291.     PieceContr.nparts = PieceContr.TicksPerMeasure / PieceContr.PartTime;
  292.     PieceContr.Twindow = PieceContr.Division / 16;
  293.  
  294.     break;
  295.   }/* case */
  296. ChangedContext=TRUE;
  297. }
  298.  
  299.  
  300. /*****************************************************/
  301. Void Quantize(N)
  302. NoteRecord **N;
  303. {
  304.   /* Still needs updating !!! */
  305.   /*****************************************************/
  306.   long dt;
  307.   MeasureTime T;
  308.   NoteRecord *WITH;
  309.  
  310.   WITH = *N;
  311.   dt = TimeDiff(WITH->EndTime, WITH->StartTime);
  312.   if (dt <= QuantTime)
  313.     return;
  314.   /* quantize notelength first */
  315.   dt = QuantTime * (long)floor((double)dt / QuantTime + 0.5);
  316.   SetTim(&T, 0, (int)dt);
  317.   /* quantize start time and end time*/
  318.   WITH->StartTime.MPart =
  319.     QuantTime * (long)floor((double)WITH->StartTime.MPart / QuantTime + 0.5);
  320.   AddTime(WITH->StartTime, T, &WITH->EndTime);
  321. }
  322.  
  323.  
  324.  
  325. /*******************************************************/
  326. Void ReadDeltaTime(ThisTrack)
  327. TrackRecord *ThisTrack;
  328. {
  329.   /*******************************************************/
  330.   long delta;
  331.   MeasureTime *WITH1;
  332.  
  333.   ThisTrack->OldOldTime = ThisTrack->OldTime;
  334.   ThisTrack->OldTime = ThisTrack->Curtime;
  335.   delta = ReadVarLen(&ThisTrack->FilRec);
  336.   WITH1 = &ThisTrack->Curtime;
  337.   /*    WriteDebugInfo('read deltatime :'+LI2S(delta)); */
  338.   if (PieceContr.TicksPerMeasure == 0) {
  339.     WITH1->MPart += delta;
  340.     return;
  341.   }
  342.   WITH1->MPart += delta;
  343.   if (WITH1->MPart >= PieceContr.TicksPerMeasure) {
  344.     WITH1->Measure += WITH1->MPart / PieceContr.TicksPerMeasure;
  345.     WITH1->MPart %= PieceContr.TicksPerMeasure;
  346.   }
  347. }
  348.  
  349.  
  350.  
  351. /******************************************************/
  352. Void InsertRest(ThisTrack)
  353. TrackRecord *ThisTrack;
  354. {
  355.   /******************************************************/
  356.   NoteRecord *N;
  357.   MeasureTime TmpTime1, TmpTime2;
  358.   Char STR1[256];
  359.   Char STR2[256];
  360.   Char STR4[256];
  361.   Char STR5[256];
  362.   Char STR6[256];
  363.  
  364.   SetTim(&TmpTime1, (int)MeasureCount, 0);
  365.   SetTim(&TmpTime2, (int)(MeasureCount + 1), 0);
  366.   N = GetFreeNote();
  367.   N->Event = REST;
  368.   /*
  369.   If (TimeDiff(TmpTime2,LastNoteOffTime)>0) AND
  370.      (TimeDiff(TmpTime1,LastNoteOffTime)<=0) Then
  371.      N^.STartTime:=LastNoteOffTime
  372.   Else
  373.      N^.STartTime:=TmpTime1;
  374.   If TimeDiff(TmpTime2,CurTime)<0 Then
  375.      N^.EndTime:=TmpTime2
  376.   Else
  377.      N^.EndTime:=CurTime;
  378.   */
  379.   N->EndTime = ThisTrack->Curtime;
  380.   N->StartTime = ThisTrack->LastNoteOffTime;
  381.   Append(&ThisTrack->NoteList, N);
  382.   sprintf(STR6, "Inserted Rest between %3d:%3ld and %3d:%3ld",
  383.       (int)N->StartTime.Measure,
  384.       N->StartTime.MPart,(int)N->EndTime.Measure,
  385.       N->EndTime.MPart);
  386.   WriteDebugInfo(STR6);
  387. }
  388.  
  389.  
  390. /******************************************************/
  391. static Void ReadNoteOn(MidCode, ThisTrack)
  392. unsigned int MidCode;
  393. TrackRecord *ThisTrack;
  394. {
  395.   /******************************************************/
  396.   NoteRecord *N, *P;
  397.   long dt;
  398.   uchar TmpVal, TmpVel;
  399.   Char STR1[256];
  400.   Char STR2[256];
  401.   Char STR4[256];
  402.   Char STR5[256];
  403.   Char STR6[256];
  404.  
  405.   TmpVal = ReadByte(&ThisTrack->FilRec);
  406.   TmpVel = ReadByte(&ThisTrack->FilRec);
  407.       /* if TmpVel=0 Than it is a Note OFF ! */
  408.  
  409.   if (TmpVel > 0) {   /* With ThisTrack */
  410.     if (ThisTrack->NotesSounding == 0) {
  411.       dt = TimeDiff(ThisTrack->Curtime, ThisTrack->LastNoteOffTime);
  412.       if (Quantizing) {
  413.     if (dt > QuantTime)   /* only insert rest if longer than QuantTime */
  414.       InsertRest(ThisTrack);
  415.       } else {
  416.     if (dt >= PieceContr.Division / 4)
  417.           /* only insert rest if longer than 1/16th note */
  418.         InsertRest(ThisTrack);
  419.       }
  420.     } else {  /* There are notes sounding, check if same note is already on */
  421.       FirstNote(ThisTrack->NoteList, &N);
  422.       P = NULL;
  423.       while (N != P) {
  424.     if (P == NULL)
  425.       P = N;
  426.     if (N->NoteVal == TmpVal && N->Event == NOTEON)
  427.     {   /* close this note down */
  428.       N->EndTime = ThisTrack->Curtime;
  429.       N->Event = NOTEOFF;
  430.       ThisTrack->LastNoteOffTime = ThisTrack->Curtime;
  431.       if (ThisTrack->NotesSounding > 0)
  432.         ThisTrack->NotesSounding--;
  433.       WriteDebugInfo("Closed down a double note");
  434.     }
  435.     NextNote(N, &N);
  436.       }
  437.     }
  438.  
  439.     N = GetFreeNote();
  440.     Append(&ThisTrack->NoteList, N);
  441.     N->MidiChnl = MidCode % 15;
  442.     N->NoteVal = TmpVal;
  443.     N->Velocity = TmpVel;
  444.     N->Event = NOTEON;
  445.     N->StartTime = ThisTrack->Curtime;
  446.     SetTim(&N->EndTime, 1000, 0);   /* set EndTime to infinity */
  447.     /*W2S(NoteArPoint)+*/
  448.     sprintf(STR6, "NoteOn : %2d Vel : %3d at %3d:%3ld",
  449.         N->NoteVal,N->Velocity,(int)ThisTrack->Curtime.Measure,
  450.         ThisTrack->Curtime.MPart);
  451.     WriteDebugInfo(STR6);
  452.     ThisTrack->NotesSounding++;
  453.     return;
  454.   }
  455.  
  456.   sprintf(STR6, "NoteOff : %2d at %3d:%3ld",
  457.       TmpVal,(int)ThisTrack->Curtime.Measure,
  458.       ThisTrack->Curtime.MPart);
  459.   WriteDebugInfo(STR6);
  460.   if (ThisTrack->NoteList.Size <= 0) {
  461.     WriteDebugInfo("There can`t be a NoteOff if there are no notes at all !");
  462.     return;
  463.   }  /* If NoteList.Size > 0 */
  464.   LastNote(ThisTrack->NoteList, &N);   /* dit gaat soms fout ... ? */
  465.   FirstNote(ThisTrack->NoteList, &P);
  466.       /* een maat kan beginnen met een NoteOff !!!! */
  467.   while (!EqualsNote(N, TmpVal) && N != P)
  468.     PrevNote(N, &N);
  469.  
  470.   if (N == NULL)
  471.     ErrorExit(6L);
  472.   else {
  473.     if (!EqualsNote(N, TmpVal))
  474.       WriteDebugInfo("Could not find note-ON for this note-OFF");
  475.     else {
  476.       if (N->Event == NOTEON) {
  477.     N->EndTime = ThisTrack->Curtime;
  478.     N->Event = NOTEOFF;
  479.       } else
  480.     WriteDebugInfo("Note was already OFF, probably a double note...");
  481.     }
  482.   }
  483.   ThisTrack->LastNoteOffTime = ThisTrack->Curtime;
  484.   if (ThisTrack->NotesSounding > 0)
  485.     ThisTrack->NotesSounding--;
  486.  
  487.   /* the Velocity value is 0 set Note Off */
  488.   /* Set Note Off */
  489. }  /* ReadNoteOn */
  490.  
  491.  
  492. /******************************************************/
  493. static Void ReadNoteOff(MidCode, ThisTrack)
  494. unsigned int MidCode;
  495. TrackRecord *ThisTrack;
  496. {
  497.   /******************************************************/
  498.   NoteRecord *N, *P;
  499.   uchar MidiChnl, velo, Note;
  500.   Char STR1[256];
  501.   Char STR2[256];
  502.   Char STR4[256];
  503.   Char STR5[256];
  504.  
  505.   MidiChnl = MidCode % 15;
  506.   Note = ReadByte(&ThisTrack->FilRec);
  507.   velo = ReadByte(&ThisTrack->FilRec);
  508.   sprintf(STR5, "NoteOff : %2d at %3d:%3ld",
  509.       Note,(int)ThisTrack->Curtime.Measure,
  510.       ThisTrack->Curtime.MPart);
  511.   WriteDebugInfo(STR5);
  512.   if (ThisTrack->NoteList.Size <= 0) {   /* with this track */
  513.     WriteDebugInfo("There can`t be a NoteOff if there are no notes at all !");
  514.     return;
  515.   }  /* If NoteList.Size > 0 */
  516.   LastNote(ThisTrack->NoteList, &N);   /* dit gaat soms fout ... ? */
  517.   FirstNote(ThisTrack->NoteList, &P);
  518.       /* een maat kan beginnen met een NoteOff !!!! */
  519.   while (!EqualsNote(N, Note) && N != P)
  520.     PrevNote(N, &N);
  521.  
  522.   if (N == NULL)
  523.     ErrorExit(6L);
  524.   else {
  525.     if (!EqualsNote(N, Note))
  526.       WriteDebugInfo("Could not find note-ON for this note-OFF");
  527.     else {
  528.       if (N->Event == NOTEON) {
  529.     N->EndTime = ThisTrack->Curtime;
  530.     N->Event = NOTEOFF;
  531.       } else
  532.     WriteDebugInfo("Note was already OFF, probably a double note...");
  533.     }
  534.   }
  535.   ThisTrack->LastNoteOffTime = ThisTrack->Curtime;
  536.   if (ThisTrack->NotesSounding > 0)
  537.     ThisTrack->NotesSounding--;
  538. }  /* ReadNoteOff */
  539.  
  540.  
  541.  
  542. /******************************************************/
  543. static Void ReadMetaText(Len, ThisTrack)
  544. int Len;
  545. TrackRecord *ThisTrack;
  546. {
  547.   /******************************************************/
  548.   NoteRecord *N;
  549.   Char STR1[256];
  550.   Char STR3[256];
  551.   Char STR4[256];
  552.  
  553.   N = GetFreeNote();
  554.   Append(&ThisTrack->NoteList, N);
  555.   N->Event = TXT;
  556.   N->MetaTxt = (Char *)malloc(21L);
  557.   if (N->MetaTxt==NULL) ErrorExit(9L);
  558.   N->StartTime = ThisTrack->Curtime;
  559.   N->EndTime = ThisTrack->Curtime;
  560.   N->EndTime.Measure++;
  561.   ReadString(N->MetaTxt, &ThisTrack->FilRec, (long)Len);
  562.   sprintf(STR4, "MetaText :%s at %3ld:%3ld",
  563.       N->MetaTxt, ThisTrack->Curtime.Measure,
  564.       ThisTrack->Curtime.MPart);
  565.   WriteDebugInfo(STR4);
  566. }  /* ReadText */
  567.  
  568.  
  569. /**********************************************************/
  570. Void ReadMetaEvent(ThisTrack)
  571. TrackRecord *ThisTrack;
  572. {
  573.   /**********************************************************/
  574.   long i, DumInt;
  575.   uchar DumByte, MetaType;
  576.   unsigned short MetaByteCnt;
  577.   long MetaLength;
  578.   NoteRecord *N;
  579.   Char STR1[256];
  580.   Char STR2[256], STR3[256], STR4[256], STR5[256], STR6[256];
  581.  
  582.   MetaType = ReadByte(&ThisTrack->FilRec);
  583.   MetaLength = ReadVarLen(&ThisTrack->FilRec);
  584.   sprintf(STR3, " Read Meta event type : %2d of %2ld bytes",
  585.       MetaType,MetaLength);
  586.   WriteDebugInfo(STR3);
  587.   MetaByteCnt = 0;
  588.   switch (MetaType) {
  589.  
  590.   case 0:
  591.     DumByte = ReadByte(&ThisTrack->FilRec);
  592.     DumInt = ReadInteger(&ThisTrack->FilRec);
  593.     break;
  594.  
  595.   case 1:
  596.   case 2:
  597.   case 3:
  598.   case 4:
  599.   case 5:
  600.   case 6:
  601.   case 7:  /* Text events */
  602.     /* DumStr:=ReadString(FilRec,MetaLength); */
  603.     ReadMetaText((int)MetaLength, ThisTrack);
  604.     break;
  605.  
  606.   case 32:   /* MIDI Chnl Prefix */
  607.     DumByte = ReadByte(&ThisTrack->FilRec);
  608.     break;
  609.  
  610.   case 47:
  611.     ThisTrack->EndOfTrackRead = true;
  612.     break;
  613.     /* End of Track */
  614.  
  615.   case 81:  /* set tempo */
  616.     PieceContr.Tempo = ReadByte(&ThisTrack->FilRec);
  617.     PieceContr.Tempo <<= 8;
  618.     PieceContr.Tempo += ReadByte(&ThisTrack->FilRec);
  619.     PieceContr.Tempo <<= 8;
  620.     PieceContr.Tempo += ReadByte(&ThisTrack->FilRec);
  621.     break;
  622.  
  623.   case 84:  /* SMPTE OffSet */
  624.     DumByte = ReadByte(&ThisTrack->FilRec);
  625.     DumByte = ReadByte(&ThisTrack->FilRec);
  626.     DumByte = ReadByte(&ThisTrack->FilRec);
  627.     DumByte = ReadByte(&ThisTrack->FilRec);
  628.     DumByte = ReadByte(&ThisTrack->FilRec);
  629.     break;
  630.  
  631.   case 88:  /* Time Sign */
  632.     if (TeXHeaderFinished) {   /* store the value on the note list */
  633.       N = GetFreeNote();
  634.       Append(&ThisTrack->NoteList, N);
  635.       N->Event = SIGNATURE;
  636.       N->NoteVal = ReadByte(&ThisTrack->FilRec);   /* NUM */
  637.       N->Velocity = ReadByte(&ThisTrack->FilRec);   /* DEN */
  638.       DumByte = ReadByte(&ThisTrack->FilRec);
  639.       DumByte = ReadByte(&ThisTrack->FilRec);
  640.       N->StartTime = ThisTrack->Curtime;
  641.       N->EndTime = ThisTrack->Curtime;
  642.       sprintf(STR6, "Signature : %2d/%2ld at %3ld:%3ld",
  643.           N->NoteVal,(long)Power(2, N->Velocity),
  644.           ThisTrack->Curtime.Measure,
  645.           ThisTrack->Curtime.MPart);
  646.       WriteDebugInfo(STR6);
  647.     } else {
  648.       PieceContr.Num = ReadByte(&ThisTrack->FilRec);
  649.       PieceContr.Den = ReadByte(&ThisTrack->FilRec);
  650.       FinishTeXHeader(PieceContr.Num, PieceContr.Den);
  651.       DumByte = ReadByte(&ThisTrack->FilRec);
  652.       DumByte = ReadByte(&ThisTrack->FilRec);
  653.       PieceContr.TicksPerMeasure = PieceContr.Division * PieceContr.Num * 4 /
  654.                    Power(2, PieceContr.Den);
  655.       if (!PieceContr.PartOverRule)
  656.     PieceContr.PartTime = PieceContr.TicksPerMeasure / PieceContr.Num;
  657.       else
  658.     PieceContr.PartTime = PieceContr.Division * 4 / PieceContr.PartType;
  659.       PieceContr.nparts = PieceContr.TicksPerMeasure / PieceContr.PartTime;
  660.       PieceContr.Twindow = PieceContr.Division / 16;
  661.       if (Quantizing)
  662.     QuantTime = PieceContr.Division * 4 / QuantTime;
  663.       sprintf(STR4, "4*%3ld*%3d div %3d = %4ld Ticks per measure",
  664.           (long)PieceContr.Division,PieceContr.Num,
  665.           PieceContr.Den,PieceContr.TicksPerMeasure);
  666.       WriteDebugInfo(STR4);
  667.     }
  668.     break;
  669.  
  670.   case 89:  /* Key signature */
  671.     if (TeXHeaderFinished) {   /* store the value on the note list */
  672.       N = GetFreeNote();
  673.       Append(&ThisTrack->NoteList, N);
  674.       N->Event = KEYSIGN;
  675.       N->NoteVal = ReadByte(&ThisTrack->FilRec);   /* KeySign */
  676.       N->Velocity = ReadByte(&ThisTrack->FilRec);   /* Minor */
  677.       N->StartTime = ThisTrack->Curtime;
  678.       N->EndTime = ThisTrack->Curtime;
  679.  
  680.       sprintf(STR4, "Keysign  : %2d at %3ld:%3ld",
  681.         (char)N->NoteVal,ThisTrack->Curtime.Measure,
  682.           ThisTrack->Curtime.MPart);
  683.       WriteDebugInfo(STR4);
  684.     } else {
  685.       PieceContr.KeySign = ReadByte(&ThisTrack->FilRec);
  686.       PieceContr.Minor = ReadByte(&ThisTrack->FilRec);
  687.       if (PieceContr.KeySign > 0) {
  688.     sprintf(STR6, "KeySignature : %2d sharps ",(int)PieceContr.KeySign);
  689.     WriteDebugInfo(STR6);
  690.       } else {
  691.     sprintf(STR2, "KeySignature : %2d flats ",(int)PieceContr.KeySign);
  692.     WriteDebugInfo(STR2);
  693.       }
  694.     }
  695.     /* with */
  696.     break;
  697.  case 127:  /* specials.... */
  698.     for (i = 1; i <= MetaLength; i++)
  699.       DumByte = ReadByte(&ThisTrack->FilRec);
  700.     break;
  701.  
  702.   default :
  703.   /*  WriteDebugInfo("Found unknown Meta event :"+B2S(MetaType)); */
  704.     sprintf(STR2,"Found unknown Meta event :%s ",B2S(STR6,(long)MetaType));
  705.     WriteDebugInfo(STR2);
  706.     for (i=1; i<=MetaLength; i++) DumByte=ReadByte(&ThisTrack->FilRec);
  707.     break;
  708.  
  709.  
  710.   }/* case */
  711. }  /* ReadMetaEvent */
  712.  
  713.  
  714.  
  715. /*****************************************************/
  716. Void ReadEvent(ThisTrack)
  717. TrackRecord *ThisTrack;
  718. {
  719.   /*****************************************************/
  720.   uchar DumByte, MidiCode;
  721.  
  722.   MidiCode = ReadByte(&ThisTrack->FilRec);
  723.   switch (MidiCode) {
  724.  
  725.   case 0xff:
  726.     ReadMetaEvent(ThisTrack);
  727.     ThisTrack->StatusByte = MidiCode;
  728.     break;
  729.  
  730.   case 0xf8:   /* do nothing */
  731.     break;
  732.     /* timing clock */
  733.  
  734.   case 0xf0:
  735.     do {   /* SysEx code */
  736.       DumByte = ReadByte(&ThisTrack->FilRec);
  737.     } while (DumByte != 0xf7);
  738.     ThisTrack->StatusByte = 0;
  739.     break;
  740.  
  741.   case 0xf1:   /* quarter frame */
  742.     DumByte = ReadByte(&ThisTrack->FilRec);
  743.     break;
  744.     /* WriteDebugInfo(' Unknown MidiEvent, type : '+B2S(MidiCode)); */
  745.  
  746.   default:
  747.     if (MidiCode >= 0x90 && MidiCode <= 0x9f) {
  748.       ReadNoteOn(MidiCode, ThisTrack);
  749.       ThisTrack->StatusByte = MidiCode;
  750.     } else if (MidiCode >= 0x80 && MidiCode <= 0x8f) {
  751.       ReadNoteOff(MidiCode, ThisTrack);
  752.       ThisTrack->StatusByte = MidiCode;
  753.     } else if (MidiCode >= 0xa0 && MidiCode <= 0xaf) {
  754.       /* polypress. */
  755.       for (i = 1; i <= 2; i++)
  756.     DumByte = ReadByte(&ThisTrack->FilRec);
  757.       ThisTrack->StatusByte = MidiCode;
  758.     } else if (MidiCode >= 0xb0 && MidiCode <= 0xbf) {
  759.       for (i = 1; i <= 2; i++)
  760.     DumByte = ReadByte(&ThisTrack->FilRec);
  761.       ThisTrack->StatusByte = MidiCode;
  762.     } else if (MidiCode >= 0xc0 && MidiCode <= 0xcf) {
  763.       DumByte = ReadByte(&ThisTrack->FilRec);
  764.       ThisTrack->StatusByte = MidiCode;
  765.     } else if (MidiCode >= 0xd0 && MidiCode <= 0xdf) {
  766.       DumByte = ReadByte(&ThisTrack->FilRec);
  767.       ThisTrack->StatusByte = MidiCode;
  768.     } else if (MidiCode >= 0xe0 && MidiCode <= 0xef) {
  769.       for (i = 1; i <= 2; i++)
  770.     DumByte = ReadByte(&ThisTrack->FilRec);
  771.       ThisTrack->StatusByte = MidiCode;
  772.     } else {
  773.       /* This is a running status */
  774.       RestoreLastRead(&ThisTrack->FilRec);
  775.       /* This will NOT work ALWAYS !!! */
  776.       switch (ThisTrack->StatusByte) {
  777.  
  778.       case 0xff:
  779.     ReadMetaEvent(ThisTrack);
  780.     break;
  781.  
  782.       case 0xf8:   /* do nothing */
  783.     break;
  784.     /* timing clock */
  785.  
  786.       case 0xf0:
  787.     do {   /* SysEx code */
  788.       DumByte = ReadByte(&ThisTrack->FilRec);
  789.     } while (DumByte != 0xf7);
  790.     break;
  791.  
  792.       case 0xf1:   /* quarter frame */
  793.     DumByte = ReadByte(&ThisTrack->FilRec);
  794.     break;
  795.  
  796.       default:
  797.     if (ThisTrack->StatusByte >= 0x90 && ThisTrack->StatusByte <= 0x9f)
  798.       ReadNoteOn(ThisTrack->StatusByte, ThisTrack);
  799.     else if (ThisTrack->StatusByte >= 0x80 &&
  800.          ThisTrack->StatusByte <= 0x8f)
  801.       ReadNoteOff(ThisTrack->StatusByte, ThisTrack);
  802.     else if (ThisTrack->StatusByte >= 0xa0 &&
  803.          ThisTrack->StatusByte <= 0xaf) {
  804.       for (i = 1; i <= 2; i++)
  805.         DumByte = ReadByte(&ThisTrack->FilRec);
  806.     } else if (ThisTrack->StatusByte >= 0xb0 &&
  807.            ThisTrack->StatusByte <= 0xbf) {
  808.       for (i = 1; i <= 2; i++)
  809.         DumByte = ReadByte(&ThisTrack->FilRec);
  810.     } else if (ThisTrack->StatusByte >= 0xc0 &&
  811.            ThisTrack->StatusByte <= 0xcf)
  812.       DumByte = ReadByte(&ThisTrack->FilRec);
  813.     else if (ThisTrack->StatusByte >= 0xd0 &&
  814.          ThisTrack->StatusByte <= 0xdf)
  815.       DumByte = ReadByte(&ThisTrack->FilRec);
  816.     else if (ThisTrack->StatusByte >= 0xe0 &&
  817.          ThisTrack->StatusByte <= 0xef) {
  818.       for (i = 1; i <= 2; i++)
  819.         DumByte = ReadByte(&ThisTrack->FilRec);
  820.     }
  821.     break;
  822.       }/* case */
  823.     }
  824.     break;
  825.   }
  826.  
  827.   /* control change */
  828.   /* progr. change */
  829.   /* channel pressure */
  830.   /* pitch wheel */
  831. }  /* ReadEvent */
  832.  
  833.  
  834.  
  835.  
  836. /**************************************************************/
  837. boolean EndOfTrackReached(ThisTrack)
  838. TrackRecord *ThisTrack;
  839. {
  840.   /*************************************************************/
  841.   if (ThisTrack->EndOfTrackRead==true && ThisTrack->SpillList.Size == 0 &&
  842.       ThisTrack->NoteList.Size == 0)
  843.     return true;
  844.   else
  845.     return false;
  846. }
  847.  
  848.  
  849. void _TP_MIDI_init()
  850. {
  851.   static int _was_initialized = 0;
  852.   if (_was_initialized++)
  853.     return;
  854. }
  855.